JS从入门到放弃-基本类型和引用类型
JS有number,string,null,undefined,boolean,array,object七种数据类型,而JS的变量,根据指向数据类型的不同,也分为两种类型,一种基本类型,一种引用类型.
1. 基本类型
基本类型包括: number, string, null, undefined, boolean这五种.但凡变量指向这五种数据类型的都称之为基本类型.
var test1 = 'hahaha'; // string
var test2 = 1; // number
var test3 = true; // boolean
假设有以上变量,那么他们在内存中栈区的存储结构大概是这样子的.
栈区指针 | 栈区值 |
test1 | hahaha |
test2 | 1 |
test3 | true |
var test = '321';
var test = '123';
var test1 = test;
console.log(test === test1); // true
执行以上语句之后,你可能会觉得变量test
的值从字符串'321'
变成了字符串'123'
.并不是值改变了,而是test
只是一个指针,上面的两条语句都只是在为同一个指针指向不同的值而已.值是不可被改变的.执行第三条语句的时候,首先初始化一个test1
变量,然后把test
的变量赋值给test1
.这种赋值称为深拷贝.如图:
指针 | 值 |
test | '123' |
test1 | '123' |
最后一条语句之间的比较其实是test
和test1
之间的值作比较.也就是console.log('123' === '123')
,之所以多此一举的解释最后两条语句,原因是因为引用类型的赋值和比较并不是如此.
2. 引用类型
引用类型包括: object和array这两种.但凡变量指向这两种数据类型的都称之为引用类型.
var china = {
tianjin: '天津',
beijing: '北京'
};
var huabei = {
tianjin: '天津',
beijing: '北京'
};
假设有以上变量,那么他们在内存中栈区和堆区的存储结构大概是这样子的.
栈区指针 | 栈区值 |
china | china对象在堆区的内存地址 |
huabei | huabei对象在堆区的内存地址 |
堆区地址 | 堆区值 |
china对象在堆区的内存地址 | china对象 |
huabei对象在堆区的内存地址 | huabei对象 |
china.handan = '邯郸';
console.log(china.handan); // '邯郸'
当我们继续执行上面语句的时候china堆区值内部的属性除了原有的tianjin
和beijing
之外又动态的添加了一个handan
属性.这说明引用类型的值是可以被改变的.
console.log(china === huabei); // false
china对象和huabei对象内的属性明明一样,但是完全相等比较符却返回了false.这进一步证明了引用类型的比较是比较两者在堆区的地址是否相同.如果我们对两个对象的内部的属性进行比较呢.
console.log(china.tianjin === huabei.tianjin) // true
这里又会返回true,这是因为我们做比较的对象的属性是基本类型.他们会比较内部的值,而不是比较两者在堆区内的地址.
最后说一下引用类型的赋值.继续上面的代码
var asia = china;
asia.tianjin = '红桥';
console.log(asia.tianjin); // 红桥
console.log(china.tianjin); // 红桥
执行上面语句你会发现明明改变的是asia的属性,但是china的属性也跟着改变了.这是因为赋给asia的值是china对象在堆区的内存地址,而不是china对象本身.两者实际上指向同一个堆区对象.也因此,改变其中任何一个的属性,另外一个也会随之更改.这种赋值也称之为浅拷贝.
栈区指针 | 栈区值 |
china | china对象在堆区的内存地址 |
asia | china对象在堆区的内存地址 |
堆区地址 | 堆区值 |
china对象在堆区的内存地址 | china对象 |
总结
基本类型:值不可变,存放于栈区,相互比较是基于值进行比较,相互赋值是深拷贝赋值.
引用类型:值可改变,同时存放于栈区和堆区,相互比较是基于在堆区内的地址,相互赋值是浅拷贝.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。